package tp.igl;

/**
 *<b> Adresse est la classe representant une Adresse IP d'un réseau</b>
 * @author Redouane
 * @author PNR KACIMI HACINI
 * @see Segement
 * @see Adresse
 */
public class AdresseIP extends Adresse {
    /**
     * Constructeur AdresseIP.
     * <p>
     *  A la construction du l'adresse prend les valeurs fournie en parametre.
     * </p>
     * @param seg1  le segement a affecté dans la position 1
     * @param seg2  le segement a affecté dans la position 2
     * @param seg3  le segement a affecté dans la position 3
     * @param seg4  le segement a affecté dans la position 4
     * @see Segment
     */
    public AdresseIP(Segment seg1,Segment seg2,Segment seg3,Segment seg4){
        super(seg1,seg2,seg3,seg4);
    }
    /**
     *Constructeur AdresseIP
     * <p>
     *A la construction l'adresse prend les valeurs fournies dans le tableau envoyé en parametre.
     * </p>
     * @param segments Tableau des Octets
     * @see Segment
     */
    public AdresseIP(Segment []segments){
        super(segments);
    }
    
    /**
     *Retourne l'adresse de réseau à partir du masque fourni.
     * @param masque le masque de reseau
     * @return l'adresse de reseau
     * @see Adresse
     * @see Masque
     */
    public AdresseIP adresseReseau(Masque masque){
        Segment []segments=new Segment[4];
        for (int i=0;i<4;i++){
            segments[i]=this.getAdresse()[i].and(masque.getAdresse()[i]);
        }
        return new AdresseIP(segments);
    }
    
    /**
     *Renvoie l'adresse Brodadcast de reseau à partir du masque fourni.
     * @param masque le masque de réseau
     * @return l'adresse Brodadcast de reseau.
     * @see Adresse
     * @see Masque
     */
    public AdresseIP broadcast(Masque masque){
        Segment []segments=new Segment[4];
        for (int i=0;i<4;i++){
            segments[i]=this.getAdresse()[i].orNot(masque.getAdresse()[i]);
        }
        return new AdresseIP(segments);
    }
    
    /**
     *Retourne la prochaine adresse IP valide. 
     * @return la prochaine adresse IP  valide
     */
    public AdresseIP nextIP(){
        Segment[] seg=new Segment[]{adresse[0],adresse[1],adresse[2],adresse[3]};
        int i=3;
        while (seg[i].getValeur()==255 && i > 0) i--;
        seg[i].setValeur(seg[i].getValeur()+1);
        while (i<4){
            if (seg[i].getValeur()==255) seg[i].setValeur(0);
            i++;
        }
        return new AdresseIP(seg);
    }
    
    /**
     *Retourne l' adresse IP précedent  . 
     * @return l' adresse IP précedent 
     */
    public AdresseIP previousIP(){
            Segment[] seg=new Segment[]{adresse[0],adresse[1],adresse[2],adresse[3]};
            int i=3;
            while (seg[i].getValeur()==0 && i > 0) i--;
            seg[i].setValeur(seg[i].getValeur()-1);
            while ( i<4){
                if (seg[i].getValeur()==0) seg[i].setValeur(255);
                i++;
            }
            return new AdresseIP(seg);
        }
     /**
     *Additionne une valeur à un Octet de l'adresse IP.
     * @param val La valeur à ajoutée.
     * @param pos Le numéro de l'octet où la valaeur sera rajoutée.
     * @return La nouvelle adresse aprés l'addition.
     */
    public AdresseIP add(int val,int pos){
        int i=pos;
        int retenue=val;

        AdresseIP result=new AdresseIP(new Segment(0),new Segment(0),new Segment(0),new Segment(0));
        result.setAdresse(this);

       while ((i>=0)&&(retenue!=0)){
           result.getAdresse()[i].setValeur((this.getAdresse()[i].valeur+retenue)%256);
           retenue=(this.getAdresse()[i].valeur+retenue)/256;
           i--;
       }
       return result;
    }

     
    /**
     * Retourne l'adresse IP du prochaine sous-reseau crée avec le nombre Magic fourni en parametre.
     * @param nbMagic Le nombre magic utilisé pour crée les sous-réseaux.
     * @return l'adresse IP du prochaine sous-reseau
     * @see NbrMagic
     */
    public AdresseIP nextSubNetwork(NbrMagic nbMagic){
        return this.add(nbMagic.getVal(), nbMagic.getOc());
    }
 }
   

    
    
